<template>
  <div class="do-exam-page">
    <!-- 练习组件 -->
    <PracticeExerciseList
      v-if="currentView === 'practice'"
      :exercises="practiceExercises"
      :submitting="practiceSubmitting"
      :exercise-title="exerciseTitle"
      @submit-practice="handlePracticeSubmit"
    />

    <!-- 练习结果展示 -->
    <PracticeResultDisplay
      v-if="currentView === 'result'"
      :exercises="practiceExercises"
      :exercise-result="exercisesResult"
      :practice-duration="practiceDuration"
      :user-answers="userAnswers"
    />

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-container">
      <a-spin size="large" tip="正在加载考试数据..." />
    </div>

    <!-- 错误状态 -->
    <div v-if="error" class="error-container">
      <a-result status="error" title="加载失败" :sub-title="error">
        <template #extra>
          <a-button type="primary" @click="loadExamData">重新加载</a-button>
          <a-button @click="handleBackToList">返回列表</a-button>
        </template>
      </a-result>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { message } from 'ant-design-vue'
import { getGenerateExam } from '@/api/generateExercisesController'
import PracticeExerciseList from '@/components/student/practice/PracticeExerciseList.vue'
import PracticeResultDisplay from '@/components/student/practice/PracticeResultDisplay.vue'
import request from '@/request'
import { API_BASE_URL } from '@/config/env'
import { BIZ_TYPE } from '@/utils/enums/DoExercisesEnum'
import { useExercisesStore } from '@/store/exercises'

// 路由相关
const route = useRoute()
const router = useRouter()

// 状态管理
const loading = ref(false)
const error = ref('')
const currentView = ref<'practice' | 'result'>('practice')

// 练习相关状态
const practiceExercises = ref<API.ExercisesVO[]>([])//加载到的练习
const exerciseTitle = ref<string> ('')
const practiceSubmitting = ref(false)//是否提交
const practiceStartTime = ref<Date | null>(null)//测试开始时间
const exercisesResult = ref<API.judgeResponse[]>([])//测试结果
/**
 * 拿到路径参数的相关参数
 */
const bizType = computed(()=> route.query.bizType)//业务类型
const setId = computed(() => route.query.setId as string)//套题id
const mode = computed(() => route.query.mode as string) // 'start' 或 'result'
//判断业务类型
/**
 * 1.bizType : question 生成题目  通过  exerciseStore 获取数据  mode start/result兼可
 * 2.bizType : taskExam 任务测试  通过  setId  加载数据  mode start/result兼可
 * 3.bizType : errorReview 错题复习  通过 exerciseStore 获取数据  mode 只能为 start
 */
const exerciseStore = useExercisesStore()
const loadExerciseData  = async ()=>{
  switch (bizType.value) {
    case BIZ_TYPE.QUESTION.toString() :{
      await loadExerciseDataForQuestion()
    }
    break
    case BIZ_TYPE.TASK_EXAM.toString()  :{
      await loadExerciseDataForTaskExam()
    }
    break;
    case BIZ_TYPE.ERROR_REVIEW.toString()  :{
      await loadExerciseDataForErrorReview()
    }
    break;
    default :{
      message.error("没有该业务类型")
    }
  }
}
const loadExerciseDataForQuestion = async ()=> {
  // 1 .先判断mode
  if (mode.value === "start") {
    //做题模式
    //2. 从store 获取数据
    practiceExercises.value = exerciseStore.getCurrentExercises()
    exerciseTitle.value =  practiceExercises.value[0]?.title || ''
  }else{
    //查看结果
    // 3.从过来的setId查询数据
    try {
      const res = await getGenerateExam({ setId: setId.value })
      if (res.data.data && res.data.code === 0) {
        practiceExercises.value = res.data.data
        exerciseTitle.value = res.data.data[0]?.title || ''
      }
    } catch (e) {
      console.error('加载考试数据失败:', e)
      error.value = '网络错误，请稍后重试'
    } finally {
      loading.value = false
    }
  }
}
const loadExerciseDataForTaskExam = async ()=>{
  if (!setId.value) {
    error.value = '缺少考试ID参数'
    return
  }
  try {
    loading.value = true
    error.value = ''
    const res = await getGenerateExam({ setId: setId.value })
    if (res.data.code === 0 && res.data.data) {
      practiceExercises.value = res.data.data
      exerciseTitle.value = res.data.data[0]?.title || ''
      // 根据模式设置视图
      if (mode.value === 'result') {
        // 查看结果模式
        //todo
        currentView.value = 'result'
      } else {
        // 开始测试模式
        practiceStartTime.value = new Date()
        currentView.value = 'practice'
      }
    } else {
      error.value = res.data.msg || '获取考试数据失败'
    }
  } catch (e) {
    console.error('加载考试数据失败:', e)
    error.value = '网络错误，请稍后重试'
  } finally {
    loading.value = false
  }
}
const loadExerciseDataForErrorReview = async ()=>{

}
// 加载考试数据
const loadExamData = async () => {
  if (!setId.value) {
    error.value = '缺少考试ID参数'
    return
  }
  try {
    loading.value = true
    error.value = ''
    const res = await getGenerateExam({ setId: setId.value })
    if (res.data.code === 0 && res.data.data) {
      practiceExercises.value = res.data.data
      exerciseTitle.value = res.data.data[0]?.title || ''
      // console.log(practiceExercises.value)
      // 根据模式设置视图
      if (mode.value === 'result') {
        // 查看结果模式
        //todo
        currentView.value = 'result'
      } else {
        // 开始测试模式
        practiceStartTime.value = new Date()
        currentView.value = 'practice'
      }
    } else {
      error.value = res.data.msg || '获取考试数据失败'
    }
  } catch (e) {
    console.error('加载考试数据失败:', e)
    error.value = '网络错误，请稍后重试'
  } finally {
    loading.value = false
  }
}

// 练习相关事件处理
const handleBackToList = () => {
  router.push('/student/my_task')
}
const userAnswers = ref<Record<string, string>>({})
// todo
/**
 * 提交 答案
 * @param answers
 * <p> id:answer
 * 1948025859061719042:"Python具有极低的内存占用，适合资源受限的环境"
 * 1948025859061719043:"树莓派（Raspberry Pi）"
 * </p>
 */
// 在组件外部定义常量
const LONG_FIELDS = ['id', 'orderId', 'userId']; // 需要处理的字段
const handlePracticeSubmit = async (answers: Record<string, string>) => {
  //拿到答案
  userAnswers.value = answers
  //转为json字符串
  const jsonAnsMap = JSON.stringify(answers)
  practiceSubmitting.value = true
  //eventSource 连接的前置准备
  let eventSource: EventSource | null = null
  let streamCompleted = false
  try {
    // 获取 axios 配置的 baseURL
    const baseURL = request.defaults.baseURL || API_BASE_URL
    // 构建URL参数
    const params = new URLSearchParams({
      id: setId.value,
      ansMap:jsonAnsMap,
    })
    const url = `${baseURL}/generateExercises/judge/stream?${params}`
    // 0.创建 EventSource 连接
    eventSource = new EventSource(url, {
      withCredentials: true,
    })
    // 1.接收消息
    eventSource.onmessage = function(event){
      try {
        // 创建正则表达式匹配目标字段
        const regex = new RegExp(
          `"(${LONG_FIELDS.join('|')})":\\s*(\\d{15,})`,
          'g'
        );

        // 在解析前替换数字为字符串
        const fixedData = event.data.replace(regex, '"$1": "$2"');
        const data = JSON.parse(fixedData);

        // 使用处理后的数据
        console.log('Received ID:', data.id); // 字符串类型
        //加入到 结果数组
        exercisesResult.value.push(data)
      } catch (e) {
        console.log("解析消息失败")
        //处理异常
        handleError(e)
      }
    }
    // 2.终止事件
    eventSource.addEventListener("done",function(){
      if (streamCompleted) return
      streamCompleted = true
      practiceSubmitting.value = false
      eventSource?.close()
    })
    // 3.处理错误
    eventSource.onerror = function() {
      if (streamCompleted || !practiceSubmitting.value) return
      // 检查是否是正常的连接关闭
      if (eventSource?.readyState === EventSource.CONNECTING) {
        streamCompleted = true
        practiceSubmitting.value = false
        eventSource?.close()

      } else {
        handleError(new Error('SSE连接错误'))
      }
    }
    // 切换到结果视图
    currentView.value = 'result'

    message.success('测试完成！')
  } catch (error) {
    console.error('提交测试失败:', error)
    message.error('提交失败，请重试')
  } finally {
    practiceSubmitting.value = false
  }
}
// 错误处理函数
const handleError = (error: unknown) => {
  console.error('生成代码失败：', error)
  message.error('生成失败，请重试')
  practiceSubmitting.value = false
}
// 计算练习耗时
const practiceDuration = computed(() => {
  if (!practiceStartTime.value) return '0 min 0 s'

  // 计算总秒数（精确到秒）
  const totalSeconds = Math.round(
    (new Date().getTime() - practiceStartTime.value.getTime()) / 1000
  )

  // 拆分分钟和剩余秒数
  const minutes = Math.floor(totalSeconds / 60)
  const seconds = totalSeconds % 60

  // 格式化输出
  return `${minutes} min ${seconds} s`
})

// 组件挂载时加载数据
onMounted(() => {
  loadExerciseData()
  // loadExamData()
})
</script>

<style scoped>
.do-exam-page {
  max-width: 1800px;
  width: 100%;
  min-height: calc(100vh - 85px - 48px);
  margin: 0 auto;
  padding: 16px 32px;
  overflow: visible;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
}

.error-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .do-exam-page {
    padding: 12px 16px;
  }
}
</style>
